﻿#ifndef _CELLSERVER_H_
#define _CELLSERVER_H_

#include "CELL.h"
#include "CELLClient.h"
#include <map>
#include <vector>
#include <thread>
#include <mutex>
#include "CELLTask.hpp"
#include "CELLTimer.hpp"

class INetEvent;

/*
	接受客户端的消息的服务
*/
class CELLServer
{
public:
	CELLServer();

	/*
		析构函数设置为虚函数，本EasyTcpSever中存储消息服务线程的类是使用
		多态的形式，调用析构函数的时候设置析构函数为虚函数就会先调用子类的析构
		函数，在子类的析构函数中调用父类(本类)的Close函数去终止本线程，
		就会防止DoSelect纯虚函数被调用
	*/
	virtual ~CELLServer();

	// 设置网络事件，在其中设置的是EasyTcpServer对象，用于触发INetEvent类中的事件
	void SetEventObj(INetEvent* event);

	// 处理网络消息 线程入口函数
	void OnRun(CELLThread* pthread);

	/*
		当主动退出服务端后本类的子类会先被释放，实现的纯虚函数也会
		被释放，如果此时OnRun函数在调用，此时调用的就是纯虚函数，
		就会报错退出
	*/
	virtual bool DoNetEvents() = 0;

	// 
	void DoMsg();

	// 客户端离开
	void OnClientLeave(CELLClient* pClient);

	// 新客户端加入
	virtual void OnClientJoin(CELLClient* pClient);

	// 接收数据 处理粘包 拆包(IOCP是不会触发这个方法的)
	int RecvData(CELLClient* pClient);

	// 检测本类中所有正式客户端队列的心跳
	void CheckTime();

	// 处理消息，响应网络消息
	void OnNetMsg(CELLClient* pCLient, DataHeader* header);

	// 接收消息(这个方法是用于IOCP的接收计数: IOCP完成接收数据的任务调用)
	void OnNetRecv(CELLClient* pClient);

	// 关闭socket
	void Close();

	// 操作客户端缓冲队列
	void AddClient(CELLClient* pClient);

	// 线程启动函数
	void Start();

	// 获取客户端队列长度
	size_t GetClientCount();

	// 释放正式客户端和缓冲客户端队列空间
	void ClearClients();

	// 添加发送消息服务
	void AddSendTask(CELLClient* pClient, DataHeader* header);

	// 设置id
	void SetId(int id);

	// 注册时间事件，单位(秒)
	unsigned int add_time_event(CELLTimer::time_callback cb, void *ctx, unsigned int after_sec, int repeat = 1);
	// 更新时间事件，单位(秒)
	void mod_time_event(unsigned int timerid, unsigned int after_sec, int repeat = 1);
	// 删除时间事件，单位(秒)
	void del_time_event(unsigned int timerid);
protected:
	// 定时事件处理
	CELLTimer _time_event;
	// 正式客户端队列
	std::map<SOCKET, CELLClient*> _clients;
	// 客户端列表是否有变化
	bool _clients_change = true;
	// 本接收消息服务id
	int _id = -1;
private:
	// 客户端缓冲队列
	std::vector<CELLClient*> _clientsBuff;
	// 客户端缓冲队列的锁
	std::mutex _mutex;
	// 网络事件对象（指向了EasyTcpServer对象，用于调用这个对象中onNetLeave，OnNetMsg等事件处理函数）
	INetEvent* _pNetEvent = nullptr;
	// 本类创建时被赋值为当前时间戳
	time_t _old_time = CELLTime::getNowInMilliSec();
	// 描述本类工作线程信息
	CELLThread _thread;
	// 用于执行一些耗io的操作
	// CellTaskServer _taskServer;
};

#endif // #ifndef _CELLSERVER_H_
